home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / disktools / disketten-tools / stow / stow.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  33KB  |  822 lines

  1. /*****************************************************************************/
  2. /** Program: Stow        Version: 0.95ß                                     **/
  3. /** Date: September 1994                                                    **/
  4. /** Author: Leonard D Atkinson II                                           **/
  5. /**                                                                         **/
  6. /** Purpose:  Stow examines a given pathname for files and then copies      **/
  7. /**           those files to a device, volume by volume, with the lease     **/
  8. /**           ammount of waste of space.  It optionally outputs a list of   **/
  9. /**           what volumes hold what files.                                 **/
  10. /**                                                                         **/
  11. /** Requires: LIST, COPY, FORMAT commands somewhere in the path.            **/
  12. /**                                                                         **/
  13. /** History (since 0.8ß):                                                   **/
  14. /**  0.85ß                                                                  **/
  15. /**       Changed command line options to use ReadArgs()                    **/
  16. /**       (As suggested by Richard Ludwig)                                  **/
  17. /**                                                                         **/
  18. /**  0.90ß                                                                  **/
  19. /**       Changed file-choosing method, now we do it recursively            **/
  20. /**                                                                         **/
  21. /**  0.95ß                                                                  **/
  22. /**       Ironed out some bugs                                              **/
  23. /**       Finally got perfect method for figuring disk space used per file  **/
  24. /**       Added options for setting blocksize and choosing if overflow      **/
  25. /**            files are copied or not                                      **/
  26. /**                                                                         **/
  27. /** This source copyright 1994 by Leonard D Atkinson II                     **/
  28. /*****************************************************************************/
  29.  
  30.  
  31. /****************************/
  32. /* INCLUDES                 */
  33. /****************************/
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <ctype.h>
  38. #include <time.h>             /*so we can make unique filename*/
  39. #include <libraries/dos.h>    /*for the checking disk space*/
  40. #include <exec/memory.h>      /*for AllocMem()*/
  41. #include <exec/types.h>       /*for ULONG definition*/
  42. #include <clib/dos_protos.h>
  43. #include <clib/exec_protos.h>
  44. #include "ansi.h"             /*My own ansi macros*/
  45.  
  46.  
  47. /****************************/
  48. /* Data Types               */
  49. /****************************/
  50. struct my_file_node {         /*For putting files into linked list*/
  51.      char filename[40];
  52.      long filesize;
  53.      struct my_file_node *next;
  54.      };
  55.  
  56. struct disk_slot {            /*for making a disk full of files*/
  57.      struct my_file_node *file;
  58.      struct disk_slot *next;
  59.      };
  60.  
  61. /****************************/
  62. /* function prototypes      */
  63. /****************************/
  64. long check_free_space(char *); /*Returns the free space on the given volume*/
  65. void bad_format(void); /*sends user format and exits*/
  66. void set_num(char *, int); /*changes the integer into ABC form*/
  67. void my_system(char *, char *);/*execute system call with error checking*/
  68. void verify_file(char *, int);/*checks given filesize to copied filesize*/
  69. void cat_files();/*tack arg2 onto arg3*/
  70. int  find_disk(struct my_file_node *, struct disk_slot *);
  71. void do_format(void); /*formats a disk, or puts info into script*/
  72.  
  73. /****************************/
  74. /* global variables         */
  75. /****************************/
  76. char fixed_size = 0;               /*FLAG: assume fixed size?*/  
  77. int assumed_size = 899072 - 512;   /*default disk size, blank noicons FFS*/
  78.                                    /*seems like we need to spare a block*/
  79. int volume_num = 0;                /*counter of number of volumes used*/
  80. int max_waste = 10*1024;           /*default maximum waste*/
  81. char output_device[40] = "";       /*where the files are copied*/
  82. char output_script[40] = "";       /*name of script file*/
  83. char format_options[40] = "";      /*options passed to FORMAT*/
  84. char current_diskname[4] = "   ";  /*four-char disk numbering*/
  85. char dos_input[80];                /*Working strings*/
  86. char archive_name[40] = "STOW_";   /*prefix for disk names*/
  87. long block_size = 512;             /*block size for output device*/
  88. FILE *fp;                          /*Generic file point for reading temp file*/
  89.                                    /*and writing to the output file          */
  90.  
  91. /*****************************************************************************/
  92. /* Main                                                                      */
  93. /*****************************************************************************/
  94. main(int argc, char *argv[]) {
  95.  
  96.      /****************************/
  97.      /* Variables                */
  98.      /****************************/
  99.      char filename[40],   /*global filename, for reading into*/
  100.           temp_file_name[80];
  101.      long filesize = 0;   /*global filesize, for reading into*/
  102.      long total = 0;      /*total bytes tally*/
  103.  
  104.      struct my_file_node *head, /*Pointers to linked list*/
  105.                          *temp, 
  106.                          *temp2;
  107.      
  108.      struct disk_slot *work_disk,
  109.                       *current_slot,
  110.                       *temp_slot;
  111.  
  112.      int count,i; /*generic count variable*/
  113.      char list_output[40] = "";/*name of list of files copied.*/
  114.      char input_dir[40] = "";/*input directory to be copied from*/
  115.  
  116.      char verify_copies = 0;
  117.      char quiet_output = 0;
  118.      char list_sort = 1;
  119.  
  120.     char    Template[]="STOW V0.95 ©1994 Leonard D Atkinson II\nFROM/A,TO/A,LIST/K,ASSUME/K/N,WASTE/K/N,BLOCKSIZE/K/N,SCRIPT/K,FORMAT/K,NAME/K,VERIFY/S,QUIET/S,NOSORT/S,NOCOPYALL/S";
  121.     struct    RDArgs * rdargs=NULL;
  122.     long         MyArgs[13];
  123.     ULONG     error_value=0;
  124.  
  125.      char copy_all = 1;
  126.  
  127.      /***********************************************************/
  128.      /* Parse command line arguments using AmigaDos's ReadArgs  */
  129.      /***********************************************************/
  130.      for(count = 0;count<13;count++) MyArgs[count] = 0;
  131.      if( rdargs = (struct RDArgs *) ReadArgs(Template,MyArgs,NULL)) {
  132.           if(MyArgs[0]) strcpy(input_dir,(char *)MyArgs[0]);          /*source dir*/
  133.  
  134.           if(MyArgs[1]) strcpy(output_device,(char *)MyArgs[1]);      /*dest dir*/
  135.  
  136.           if(MyArgs[2]) strcpy(list_output,(char *)MyArgs[2]);        /*output file*/
  137.  
  138.           if(MyArgs[4]){                                              /*Max waste*/
  139.                max_waste = *(long *)MyArgs[4];
  140.                max_waste *= 1024;
  141.                printf("max waste is %d\n", max_waste);
  142.                }
  143.  
  144.           if(MyArgs[5]) {
  145.                block_size = *(long *)MyArgs[5];
  146.                printf("Setting block size to %d.\n", block_size);
  147.                if(block_size == 0) {
  148.                     ChangeColors(YELLOW,BLACK);
  149.                     printf("Block sizes of 0 are bad luck!\n");
  150.                     ChangeColors(RED,BLACK);
  151.                     exit(1);
  152.                     }
  153.                }
  154.  
  155.           if(MyArgs[6]) {                                             /*to script*/
  156.                strcpy(output_script,(char *)MyArgs[6]);
  157.                }
  158.  
  159.           if(MyArgs[7]) {                                             /*format*/
  160.                /*if options are provided, do it, else just*/
  161.                /*put a space in there for signaling purposes*/
  162.                if(strlen((char *)MyArgs[7])) {
  163.                     strcpy(format_options,(char *)MyArgs[7]);
  164.                     }
  165.                else {
  166.                     strcpy(format_options," ");
  167.                     }
  168.                }
  169.  
  170.           if(MyArgs[8]){                                              /*name*/
  171.                strncpy(archive_name,(char *)MyArgs[8],16);
  172.                strcat(archive_name,"_");
  173.                /*turn all non-printables into underscores*/
  174.                for(i = 0; i<strlen(archive_name); i++)
  175.                     if(isspace(archive_name[i])) archive_name[i] = '_';
  176.                }
  177.  
  178.           if(MyArgs[9]) verify_copies = 1;                            /*verify*/
  179.                
  180.           if(MyArgs[10]) quiet_output = 1;                             /*quiet*/
  181.  
  182.           if(MyArgs[11]) list_sort = 0;                               /*sort*/
  183.  
  184.           if(MyArgs[12]) 
  185.                copy_all = 0;                    /*don't copy all files*/
  186.  
  187.           if(MyArgs[3]){                                              /*assumed size*/
  188.                assumed_size=*(long *)MyArgs[3];
  189.                assumed_size *= 1024;
  190.                assumed_size -= block_size; /*spare one block*/
  191.                fixed_size = 1;
  192.                }
  193.  
  194.           FreeArgs((struct RDArgs *) rdargs); /*done parsing, so free memory*/
  195.           }
  196.      else {
  197.           error_value=IoErr();
  198.           PrintFault(error_value,"Stow");
  199.           }
  200.  
  201.      if((strlen(output_device) == 0) || (strlen(input_dir) == 0)) bad_format();
  202.  
  203.      if((strlen(output_script) > 0) && (fixed_size != 1)) {
  204.           printf("Output scripts require an assumed size.\n");
  205.           printf("Auto-enabling an assumed size of %d.\n",assumed_size+block_size);
  206.           fixed_size = 1;
  207.           }
  208.  
  209.      if(quiet_output != 1) printf("Assembling the list of files to be stowed.\n");
  210.  
  211.      /***********************************************************/
  212.      /*Call the LIST command to make a list of all the files    */
  213.      /*name the file with current time afterwards to avoid      */
  214.      /*two versions of the program from clobbering each other's */
  215.      /*temp files.                                              */
  216.      /***********************************************************/
  217.      sprintf(temp_file_name, "t:stow%d", (unsigned int)time(NULL));
  218.      sprintf(dos_input, "list %s %s >%s", input_dir, "lformat \"%S %L\"", temp_file_name );
  219.      my_system(dos_input,"Can't create file list in temp!");     
  220.  
  221.      fp = fopen(temp_file_name,"r");  /*open the file just created*/
  222.      if(fp == NULL) {
  223.           ChangeColors(YELLOW,BLACK);
  224.           printf("For some reason the temp file can't be opened!\n");
  225.           ChangeColors(RED,BLACK);
  226.           exit(1);
  227.           }
  228.  
  229.      /*Make a head node*/
  230.      head = (struct my_file_node *) AllocMem( sizeof(struct my_file_node),
  231.           MEMF_PUBLIC | MEMF_CLEAR );
  232.      if(head == NULL) {
  233.           ChangeColors(YELLOW,BLACK);
  234.           printf("Couldn't allocate memory!\n");
  235.           ChangeColors(RED,BLACK);
  236.           exit(1);
  237.           }          
  238.      head->next = NULL;
  239.      head->filesize = 0;
  240.      strcpy(head->filename, "HEAD NODE");
  241.  
  242.      /****************************/
  243.      /* Build Linked List        */
  244.      /****************************/
  245.      while(fscanf(fp, "%s %d",filename,&filesize) != EOF) {/*while more*/
  246.           if((filesize > 0) && (strlen(filename)>0)) {
  247.                             /*only bother making nodes for non-empty files*/
  248.                             /*with valid names                            */
  249.  
  250.                total += filesize;
  251.  
  252.                /*make a new node*/
  253.                temp = (struct my_file_node *) 
  254.                     AllocMem( sizeof(struct my_file_node),
  255.                               MEMF_PUBLIC | MEMF_CLEAR );
  256.                if(temp == NULL) {
  257.                     ChangeColors(YELLOW,BLACK);
  258.                     printf("Couldn't allocate memory!\n");
  259.                     ChangeColors(RED,BLACK);
  260.                     exit(1);
  261.                     } 
  262.                strcpy(temp->filename, filename);/*fill with information*/
  263.                temp->filesize = filesize;
  264.  
  265.                temp2 = head;/*Find the right place to insert new node*/
  266.  
  267.                if(list_sort == 1) {/*find insertion point*/
  268.                     while((temp2->next != NULL) && 
  269.                          (((temp2->next)->filesize) > (temp->filesize))) 
  270.                               temp2 = temp2->next;
  271.                     }
  272.                else {
  273.                     /*just add to end of list now*/
  274.                     while(temp2->next != NULL) temp2 = temp2->next;
  275.                     }
  276.  
  277.                /*Insert Node*/
  278.                if(temp2->next == NULL) {
  279.                     temp2->next = temp;
  280.                     temp->next = NULL;
  281.                     }
  282.                else {
  283.                     temp->next = temp2->next;
  284.                     temp2->next = temp;
  285.                     }
  286.                }
  287.           }
  288.      fclose(fp); /*close temp file*/
  289.      if(DeleteFile(temp_file_name) == TRUE) { /*delete temp file*/
  290.           ChangeColors(YELLOW,BLACK);
  291.           printf("For some reason the temp file can't be deleted!\n");
  292.           ChangeColors(RED,BLACK);
  293.           exit(1);
  294.           }
  295.  
  296.       if(strlen(list_output) > 0) { /*if requested, open output file*/
  297.           fp = fopen(list_output,"w");
  298.           if(fp == NULL) {
  299.                ChangeColors(YELLOW,BLACK);
  300.                printf("Error--Cannot open file %s for output.\n",list_output);
  301.                ChangeColors(RED,BLACK);
  302.                exit(1);
  303.                }
  304.           fprintf(fp,"!!! Files Stowed !!!\n");
  305.           fclose(fp);
  306.           }    
  307.      if(strlen(output_script) > 0) { /*if requested, open output script*/
  308.           fp = fopen(output_script,"w");
  309.           if(fp == NULL) {
  310.                ChangeColors(YELLOW,BLACK);
  311.                printf("Error--Cannot open file %s for output.\n",output_script);
  312.                ChangeColors(RED,BLACK);
  313.                exit(1);
  314.                }
  315.           fprintf(fp,"echo Stowing %s from script\n",input_dir);
  316.           fclose(fp);
  317.           }
  318.  
  319.      /***************************************************************/
  320.      /*if the input directory doesn't end in / or : then assume it's*/
  321.      /*a directory and put the / in for later catenation.           */
  322.      /***************************************************************/
  323.      if((input_dir[strlen(input_dir) - 1] != '/') && 
  324.         (input_dir[strlen(input_dir) - 1] != ':')) 
  325.           strcat(input_dir, "/");
  326.           
  327.      if(quiet_output != 1) {
  328.           printf("%d total bytes to be packed.\n",total);
  329.           printf("This will take about %d FFS floppies.\n",(total/890000)+1);
  330.           }
  331.  
  332.      /* make work_disk head node */
  333.      work_disk = (struct disk_slot *) AllocMem( sizeof(struct disk_slot),
  334.           MEMF_PUBLIC | MEMF_CLEAR );
  335.      if(work_disk == NULL) {
  336.           ChangeColors(YELLOW,BLACK);
  337.           printf("Couldn't allocate memory!\n");
  338.           ChangeColors(RED,BLACK);
  339.           exit(1);
  340.           }          
  341.      work_disk->next = NULL;
  342.      work_disk->file = head;
  343.  
  344.      if(strlen(output_script) != 0) { /*Add disk prompt to script*/
  345.           fp = fopen(output_script,"a");
  346.           if(fp == NULL) {
  347.                ChangeColors(YELLOW,BLACK);
  348.                printf("Error--Cannot open file %s for output.\n",temp_file_name);
  349.                ChangeColors(RED,BLACK);
  350.                exit(1);
  351.                }
  352.           fprintf(fp, "ask \"next disk\"\n");
  353.           fclose(fp);
  354.           }
  355.      else {
  356.           printf("Please put a disk in %s and press RETURN.\n",output_device);
  357.           getchar();
  358.           }
  359.  
  360.      /*If we need to format a disk, do it*/
  361.      if(strlen(format_options) != 0) {
  362.           do_format();
  363.           }
  364.  
  365.      if(fixed_size == 0) { /*we don't have fixed sizes*/
  366.           assumed_size = check_free_space(output_device);
  367.           assumed_size -= block_size;
  368.           }
  369.  
  370.      /****************************/
  371.      /* Main Loop                */
  372.      /****************************/
  373.      while(find_disk(head->next, work_disk)) {
  374.           /*made a disk, so copy the files*/
  375.  
  376.           current_slot = work_disk->next;
  377.           while(current_slot != NULL) {
  378.                temp = head;
  379.                while(temp->next != current_slot->file) {
  380.                     temp = temp->next;
  381.                     }
  382.                temp->next = temp->next->next;
  383.                /*Inform user what's going on*/
  384.                if(quiet_output != 1) {
  385.                     printf("Copying %s to disk %d\n",
  386.                               current_slot->file->filename,
  387.                               volume_num);
  388.                     }
  389.  
  390.                /*assemble dos call to COPY*/
  391.                sprintf(dos_input, "copy %s%s %s",input_dir,current_slot->file->filename,output_device);
  392.  
  393.                if(strlen(output_script) > 0) { /*if requested, open output file*/
  394.                     fp = fopen(output_script,"a");
  395.                     if(fp == NULL) {
  396.                          ChangeColors(YELLOW,BLACK);
  397.                          printf("Error--Cannot open file %s for output.\n",list_output);
  398.                          ChangeColors(RED,BLACK);
  399.                          exit(1);
  400.                          }
  401.                     fprintf(fp,"%s\n",dos_input);
  402.                     fclose(fp);
  403.                     }
  404.                else {
  405.                     my_system(dos_input,"Copy Failed!\n");
  406.                     }
  407.  
  408.                if(verify_copies == 1) {
  409.                     sprintf(filename,"%s%s",input_dir,current_slot->file->filename);
  410.                     verify_file(filename,current_slot->file->filesize);
  411.                     }
  412.  
  413.                /*Add filename to output file*/
  414.                if(strlen(list_output) > 0) { /*if requested, open output file*/
  415.                     fp = fopen(list_output,"a");
  416.                     if(fp == NULL) {
  417.                          ChangeColors(YELLOW,BLACK);
  418.                          printf("Error--Cannot open file %s for output.\n",list_output);
  419.                          ChangeColors(RED,BLACK);
  420.                          exit(1);
  421.                          }
  422.                     fprintf(fp,"%-32.32s %6d %s%s\n",current_slot->file->filename,
  423.                          current_slot->file->filesize,archive_name,current_diskname);
  424.                     fclose(fp);
  425.                     }
  426.  
  427.                /*Free up the memory from the nodes*/
  428.                FreeMem(current_slot->file, sizeof(struct disk_slot));
  429.                temp_slot = current_slot;
  430.                current_slot = current_slot->next;
  431.                FreeMem(temp_slot, sizeof(struct disk_slot));
  432.                }
  433.  
  434.           work_disk->next = NULL;
  435.  
  436.           /*Quick check: do we have enough to make a disk?*/
  437.           temp = head->next;
  438.           count = 0;
  439.           while(temp != NULL) {
  440.                count += temp->filesize;
  441.                temp = temp->next;
  442.                }
  443.           if(count < (assumed_size - max_waste)) {
  444.                break;
  445.                }
  446.  
  447.           if(strlen(output_script) > 0) {
  448.                fp = fopen(output_script,"a");
  449.                if(fp == NULL) {
  450.                     ChangeColors(YELLOW,BLACK);
  451.                     printf("Error--Cannot open file %s for output.\n",list_output);
  452.                     ChangeColors(RED,BLACK);
  453.                     exit(1);
  454.                     }
  455.                fprintf(fp, "ask \"next disk\"\n");
  456.                fclose(fp);
  457.                }
  458.           else {
  459.                printf("Remove the volume in %s and put in another.\n",output_device);
  460.                printf("Press RETURN");
  461.                getchar();
  462.                }
  463.  
  464.           volume_num++; /*advance to next volume number*/
  465.  
  466.           /*If we need to format a disk, do it*/
  467.           if(strlen(format_options) != 0) {
  468.                do_format();
  469.                }
  470.  
  471.           if(fixed_size == 0) { /*we don't have fixed sizes*/
  472.                assumed_size = check_free_space(output_device);
  473.                }
  474.           }
  475.  
  476.      if(copy_all == 1) {
  477.           printf("Copying remaining files to last disk.\n");
  478.  
  479.           if(strlen(output_script) > 0) {
  480.                fp = fopen(output_script,"a");
  481.                if(fp == NULL) {
  482.                     ChangeColors(YELLOW,BLACK);
  483.                     printf("Error--Cannot open file %s for output.\n",list_output);
  484.                     ChangeColors(RED,BLACK);
  485.                     exit(1);
  486.                     }
  487.                fprintf(fp, "ask \"next disk\"\n");
  488.                fclose(fp);
  489.                }
  490.           else {
  491.                printf("Remove the volume in %s and put in another.\n",output_device);
  492.                printf("Press RETURN");
  493.                getchar();
  494.                }
  495.  
  496.           volume_num++; /*advance to next volume number*/
  497.  
  498.           /*If we need to format a disk, do it*/
  499.           if(strlen(format_options) != 0) {
  500.                do_format();
  501.                }
  502.  
  503.           temp = head->next;
  504.           while(temp != NULL) {
  505.                /*Inform user what's going on*/
  506.                if(quiet_output != 1) {
  507.                     printf("Copying %s to disk %d\n",
  508.                               temp->filename,
  509.                               volume_num);
  510.                     }
  511.  
  512.                /*assemble dos call to COPY*/
  513.                sprintf(dos_input, "copy %s%s %s",input_dir,temp->filename,output_device);
  514.  
  515.                if(strlen(output_script) > 0) { /*if requested, open output file*/
  516.                     fp = fopen(output_script,"a");
  517.                     if(fp == NULL) {
  518.                          ChangeColors(YELLOW,BLACK);
  519.                          printf("Error--Cannot open file %s for output.\n",list_output);
  520.                          ChangeColors(RED,BLACK);
  521.                          exit(1);
  522.                          }
  523.                     fprintf(fp,"%s\n",dos_input);
  524.                     fclose(fp);
  525.                     }
  526.                else {
  527.                     my_system(dos_input,"Copy Failed!\n");
  528.                     }
  529.  
  530.                if(verify_copies == 1) {
  531.                     sprintf(filename,"%s%s",input_dir,temp->filename);
  532.                     verify_file(filename,temp->filesize);
  533.                     }
  534.  
  535.                /*Add filename to output file*/
  536.                if(strlen(list_output) > 0) { /*if requested, open output file*/
  537.                     fp = fopen(list_output,"a");
  538.                     if(fp == NULL) {
  539.                          ChangeColors(YELLOW,BLACK);
  540.                          printf("Error--Cannot open file %s for output.\n",list_output);
  541.                          ChangeColors(RED,BLACK);
  542.                          exit(1);
  543.                          }
  544.                     fprintf(fp,"%-32.32s %6d %s%s\n",temp->filename,
  545.                          temp->filesize,archive_name,current_diskname);
  546.                     fclose(fp);
  547.                     }
  548.                head->next = temp->next;
  549.                FreeMem(temp, sizeof(struct my_file_node));
  550.                temp = head->next;
  551.                }
  552.           }
  553.      else {
  554.           printf("\nno more disks can be made\n");
  555.           }
  556.  
  557.      }/*end of main*/
  558.  
  559. /******************************************************************************/
  560. /**do_format()                                                               **/
  561. /**Formats a disk                                                            **/
  562. /******************************************************************************/
  563. void do_format() {
  564.  
  565.      set_num(current_diskname,volume_num);/*make new disk name*/
  566.  
  567.      sprintf(dos_input,"FORMAT DRIVE %s NAME %s%s %s",
  568.           output_device,archive_name,current_diskname, format_options);
  569.      if(strlen(output_script) != 0) { /*if requested, open output file*/
  570.           fp = fopen(output_script,"a");
  571.           if(fp == NULL) {
  572.                ChangeColors(YELLOW,BLACK);
  573.                printf("Error--Cannot open file %s for output.\n",output_script);
  574.                ChangeColors(RED,BLACK);
  575.                exit(1);
  576.                }
  577.           fprintf(fp, "%s\n",dos_input);
  578.           fclose(fp);
  579.           }
  580.      else {
  581.           my_system(dos_input,"Can't format disk!\n");
  582.           }
  583.  
  584.      }/*end of do_format*/
  585.  
  586.  
  587. /******************************************************************************/
  588. /**find_disk()                                                               **/
  589. /**Recursively builds the perfect disk                                       **/
  590. /******************************************************************************/
  591. int find_disk(struct my_file_node *input_files,
  592.                struct disk_slot *output_disk) {
  593.  
  594.      struct my_file_node *current_file;
  595.      struct disk_slot *current_slot;
  596.      long current_size;
  597.  
  598.      /*count up the disk size*/
  599.      current_size = 0;
  600.      current_slot = output_disk->next;
  601.      while(current_slot != NULL) {
  602.           current_size += current_slot->file->filesize;
  603.           current_slot = current_slot->next;
  604.           }
  605.  
  606.      current_file = input_files;
  607.      while(current_file != NULL) {
  608.           if(((((((current_file->filesize/block_size)+1)/72)+1)*block_size) + current_size) > assumed_size) {
  609.                current_file = current_file->next;
  610.                }
  611.           else { /*current_file will fit on disk*/
  612.                /*add file*/
  613.                current_slot = output_disk;
  614.                while(current_slot->next != NULL) current_slot = current_slot->next;
  615.  
  616.                current_slot->next = (struct disk_slot *) AllocMem( sizeof(struct disk_slot),
  617.                     MEMF_PUBLIC | MEMF_CLEAR );
  618.                if(current_slot == NULL) {
  619.                     ChangeColors(YELLOW,BLACK);
  620.                     printf("Couldn't allocate memory!\n");
  621.                     ChangeColors(RED,BLACK);
  622.                     exit(1);
  623.                     }
  624.                current_slot->next->next = NULL;
  625.                current_slot->next->file = current_file;
  626.  
  627.                if(((((((current_file->filesize/block_size)+1)/72)+1)*block_size) + current_size) > (assumed_size - max_waste)) {
  628.                     /*we've made a good disk*/
  629.                     return(TRUE);
  630.                     }
  631.                else { /*we need more files*/
  632.                     if(find_disk(current_file->next, output_disk)) {
  633.                          /*we find a disk after this*/
  634.                          return(TRUE);
  635.                          }
  636.                     else {/*dead end, no disks found*/
  637.                          /*remove file, try next one*/
  638.                          FreeMem(current_slot->next, sizeof(struct disk_slot));
  639.                          current_slot->next = NULL;
  640.                          current_file = current_file->next;
  641.                          
  642.                          }
  643.                     }
  644.                }
  645.           }/*end of while loop*/
  646.           return(FALSE);/*no disks beyond this point*/
  647.      }
  648.  
  649.  
  650.  
  651.  
  652. /******************************************************************************/
  653. /**check_free_space()                                                        **/
  654. /**Takes the name of a device and returns the bytes free                     **/
  655. /******************************************************************************/
  656. long check_free_space(char *checked_device) {
  657.  
  658.      /*************************/
  659.      /* Variables             */
  660.      /*************************/
  661.      struct FileLock *lock;
  662.      struct InfoData *info_ptr;
  663.      long return_value;
  664.  
  665.      /***********************************/
  666.      /*Get a new InfoData structure     */
  667.      /*AllocMem assures a 4 byte boundry*/
  668.      /***********************************/
  669.      info_ptr = (struct InfoData *) AllocMem( sizeof( struct InfoData ),
  670.           MEMF_PUBLIC | MEMF_CLEAR );
  671.      if( info_ptr == NULL ) {
  672.           ChangeColors(YELLOW,BLACK);
  673.           printf("Couldn't allocate memory!\n");
  674.           ChangeColors(RED,BLACK);
  675.           exit(1);
  676.           }
  677.  
  678.      /*get a file lock*/
  679.      lock = (struct FileLock *) Lock( checked_device, SHARED_LOCK );
  680.      if( lock == NULL ) {
  681.           ChangeColors(YELLOW,BLACK);
  682.           printf("Could not lock your desination device!\n");
  683.           ChangeColors(RED,BLACK);
  684.           FreeMem( info_ptr, sizeof( struct InfoData ) );
  685.           exit(1);
  686.           }
  687.      if( Info((BPTR) lock, info_ptr ) == NULL ) {
  688.           ChangeColors(YELLOW,BLACK);
  689.           printf("Could not examine your destination device!\n");
  690.           ChangeColors(RED,BLACK);
  691.           FreeMem( info_ptr, sizeof( struct InfoData ) );
  692.           UnLock((BPTR)lock );  
  693.           exit(1);
  694.           }
  695.  
  696.      /*Set return value*/
  697.      return_value = (info_ptr->id_NumBlocks - info_ptr->id_NumBlocksUsed) 
  698.             * info_ptr->id_BytesPerBlock;
  699.  
  700.      /*Free up the file and memory*/
  701.      UnLock((BPTR) lock );  
  702.      FreeMem( info_ptr, sizeof( struct InfoData ) );
  703.      
  704.      return(return_value);
  705.      }/*end of check_free_space() */
  706.  
  707. /******************************************************************************/
  708. /**  bad_format                                                              **/
  709. /**  instructs user that a bad format of options was given                   **/
  710. /******************************************************************************/
  711. void bad_format(){
  712.      printf("Usage: stow <input directory> <output directory>\n");
  713.      printf("Followed by these options:\n");
  714.      printf("LIST <filename>       create a file with a list of all files\n");
  715.      printf("ASSUME [n]            assume disk size nKbytes, or 842K default\n");
  716.      printf("WASTE <n>             allow a maximum of nKbytes of unused space\n");
  717.      printf("SCRIPT <filename>     put all commands into file instead\n");
  718.      printf("FORMAT \"<options>\"    format each disk using options\n");
  719.      printf("NAME <name>           name each disk with name_XXX\n");
  720.      printf("VERIFY                verify each copy\n");
  721.      printf("QUIET                 don't output to console\n");
  722.      printf("NOSORT                don't sort files before building disks\n");
  723.      printf("BLOCKSIZE <n>         set block size to n\n");
  724.      printf("NOCOPYALL             don't copy the leftover files\n");  
  725.      exit(1);
  726.      }
  727.  
  728.  
  729. /******************************************************************************/
  730. /**  set_num                                                                 **/
  731. /**  converts int to letter form for naming disks                            **/
  732. /******************************************************************************/
  733. void set_num(char *output, int num) {
  734.  
  735.      output[0] = 'A' + (num/(26*26));
  736.      num -= ((num/(26*26)) * (26*26));
  737.      output[1] = 'A' + (num/(26));
  738.      num -= ((num/(26)) * 26);
  739.      output[2] = 'A' + num;
  740.  
  741.      return;
  742.      }
  743.  
  744. /******************************************************************************/
  745. /** my_system                                                                **/
  746. /** Gets rid of a bunch of repetitive calls to system()                      **/
  747. /******************************************************************************/
  748. void my_system(char *sys_call, char *error_string) {
  749.  
  750.      if(system(sys_call) != 0) {
  751.           ChangeColors(YELLOW,BLACK);
  752.           printf("%s\n",error_string);
  753.           ChangeColors(RED,BLACK);
  754.           exit(1);
  755.           }
  756.      return;
  757.      }
  758.  
  759. /******************************************************************************/
  760. /** Verify_File()                                                            **/
  761. /** Checks actual filesize verses the original                               **/
  762. /******************************************************************************/
  763. void verify_file(char *checked_file, int check_size) {
  764.      /*************************/
  765.      /* Variables             */
  766.      /*************************/
  767.      struct FileLock *lock;
  768.      struct FileInfoBlock *fib_ptr;
  769.  
  770.      /***********************************/
  771.      /*Get a new FileInfoBlock structure*/
  772.      /*AllocMem assures a 4 byte boundry*/
  773.      /***********************************/
  774.      fib_ptr = (struct FileInfoBlock *)
  775.           AllocMem( sizeof( struct FileInfoBlock ),
  776.           MEMF_PUBLIC | MEMF_CLEAR );
  777.      /* Check if we have allocated the memory successfully: */
  778.      if( fib_ptr == NULL ) {
  779.           ChangeColors(YELLOW,BLACK);
  780.           printf("Couldn't allocate memory!\n");
  781.           ChangeColors(RED,BLACK);
  782.           exit(1);
  783.           }
  784.  
  785.      /*get a file lock*/
  786.      lock = (struct FileLock *) Lock( checked_file, SHARED_LOCK );
  787.      if( lock == NULL ) {
  788.           ChangeColors(YELLOW,BLACK);
  789.           printf("Could not lock %s!\n",checked_file);
  790.           ChangeColors(RED,BLACK);
  791.           FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
  792.           exit(1);
  793.           }
  794.  
  795.      if( Examine((BPTR) lock, fib_ptr ) == NULL ) {
  796.           ChangeColors(YELLOW,BLACK);
  797.           printf("Could not examine %s!\n",checked_file);
  798.           ChangeColors(RED,BLACK);
  799.           FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
  800.           UnLock((BPTR) lock );  
  801.           exit(1);
  802.           }
  803.  
  804.      /*Set return value*/
  805.      if(fib_ptr->fib_Size != check_size) {
  806.           ChangeColors(YELLOW,BLACK);
  807.           printf("%s did not verify!\n",checked_file);
  808.           ChangeColors(RED,BLACK);
  809.           FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
  810.           UnLock((BPTR) lock );  
  811.           exit(1);
  812.           }
  813.  
  814.      /*Free up the file and memory*/
  815.      UnLock((BPTR) lock );  
  816.      FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
  817.      
  818.      return;
  819.      }/*end of verify_file() */
  820.  
  821.  
  822.